package util.util.excel;

import util.model.common.ExcelInfo;
import util.model.common.FieldConfig;
import util.model.common.FieldInfo;
import util.util.DevBeanUtil;
import util.util.DevFileUtil;
import util.util.annotation.FormatType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;

import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author liW
 * @version 1.0
 * @date 2019-11-4 13:32
 */
public class ReadExcel {


    /**
     * 读取Excel数据
     *
     * @param excelInfo      excel
     * @return 读取的数据集合
     */
    public  static <T> List<T> read2Model(ExcelInfo<T> excelInfo) {
        return read2Model(excelInfo.getModel(), excelInfo.getPath(), excelInfo.getSheetPage(), excelInfo.getStartRow());
    }

    /**
     * 读取Excel数据
     *
     * @param excelInfo      excel
     * @return 读取的数据集合
     */
    public  static String readName(ExcelInfo excelInfo) {
        Sheet sheet = DevFileUtil.getSheet(excelInfo.getPath(), excelInfo.getSheetPage());
        return sheet.getSheetName();
    }

    /**
     * 读取Excel数据
     *
     * @param path      excel路径
     * @param sheetPage 读取的sheet页码
     * @param startRow  开始的行号
     * @param model     字段
     * @return 读取的数据集合
     */
    public  static <T> List<T> read2Model(Class<T> model, String path, int sheetPage, int startRow) {
        String[] fields = Arrays.stream(model.getDeclaredFields()).map(Field::getName).toArray(String[]::new);
        List<Map<String, String>> list = read2Map(path, sheetPage, startRow, fields);
        return conver(list, model);
    }

    /**
     * 读取Excel数据
     *
     * @param path      excel路径
     * @param sheetPage 读取的sheet页码
     * @param startRow  开始的行号
     * @param model     字段
     * @return 读取的数据集合
     */
    public  static <T> List<T> read2Model(Class<T> model, String path, int sheetPage, int startRow, int endRow) {
        String[] fields = Arrays.stream(model.getDeclaredFields()).map(Field::getName).toArray(String[]::new);
        List<Map<String, String>> list = read2Map(path, sheetPage, startRow, endRow, fields);
        return conver(list, model);
    }

    /**
     * map -> bean
     *
     * @param list
     * @param mode
     * @param <T>
     * @return
     */
    private static <T> List<T> conver(List<Map<String, String>> list, Class<T> mode) {
        Field[] declaredFields = mode.getDeclaredFields();
        FieldConfig fieldConfig = new FieldConfig();
        for (Field field : declaredFields) {
            String name = field.getName();
            FormatType annotation = field.getAnnotation(FormatType.class);
            fieldConfig.beanConvert(name, name, String.valueOf(annotation.length()), String.valueOf(annotation.scale()), annotation.dateFormat());
        }
        List<T> beanList = new ArrayList<>(list.size());
        for (Map<String, String> stringStringMap : list) {
            T t = DevBeanUtil.mapCovert(stringStringMap, mode, fieldConfig);
            beanList.add(t);
        }
        return beanList;
    }

    /**
     * 读取Excel数据
     *
     * @param path      excel路径
     * @param sheetPage 读取的sheet页码
     * @param startRow  开始的行号
     * @param fields    字段
     * @return 读取的数据集合
     */
    public static List<Map<String, String>> read2Map(String path, int sheetPage, int startRow, String[] fields) {
        Sheet sheet = DevFileUtil.getSheet(path, sheetPage);
        int lastRowNum = sheet.getLastRowNum();
        List<Map<String, String>> list = new ArrayList<>(lastRowNum + 1);
        Map<String, String> map;
        for (int i = startRow; i <= lastRowNum; i++) {
            Row row = sheet.getRow(i);
            map = new HashMap<>(fields.length);
            int n = 0;
            for (String field : fields) {
                String value = DevFileUtil.getCellValueNull(row, n++);
                map.put(field, value);
            }
            list.add(map);
        }
        return list;
    }

    /**
     * 读取Excel数据
     *
     * @param path      excel路径
     * @param sheetPage 读取的sheet页码
     * @param startRow  开始的行号
     * @param fields    字段
     * @return 读取的数据集合
     */
    public static List<Map<String, String>> read2Map(String path, int sheetPage, int startRow, int endRow, String[] fields) {
        Sheet sheet = DevFileUtil.getSheet(path, sheetPage);
        List<Map<String, String>> list = new ArrayList<>(endRow + 1);
        Map<String, String> map;
        for (int i = startRow; i <= endRow; i++) {
            Row row = sheet.getRow(i);
            map = new HashMap<>(fields.length);
            int n = 0;
            for (String field : fields) {
                String value = DevFileUtil.getCellValueNull(row, n++);
                map.put(field, value);
            }
            list.add(map);
        }
        return list;
    }


    /**
     * 获取List集合
     *
     * @param path      路径
     * @param sheetPage sheetPage
     * @param startRow  startRow
     * @return 获取List集合
     */
    public static List<FieldInfo> getFieldModeList(String path, int sheetPage, int startRow) {
        return ReadExcel.read2Model(FieldInfo.class, path, sheetPage, startRow);
    }

    /**
     * 获取Map集合(根据表明分组)
     *
     * @param path      路径
     * @param sheetPage sheetPage
     * @param startRow  startRow
     * @return 获取Map集合(根据表明分组)
     */
    public static Map<String, List<FieldInfo>> getFieldModeMap(String path, int sheetPage, int startRow) {
        List<FieldInfo> fieldModeDTOS = ReadExcel.read2Model(FieldInfo.class, path, sheetPage, startRow);
        return fieldModeDTOS.stream()
                .collect(Collectors.groupingBy(item -> item.getFieldName() == null ? "" : item.getFieldName(), Collectors.toList()));

    }

}
